﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Ssrtr
{
    public static class Sip
    {

        /// <summary>
        /// Compile the responses for the sip requests
        /// </summary>
        /// <param name="request">The encoded mu-law byte</param>
        /// <param name="codec">The encoded mu-law byte</param>
        /// <param name="ip">The encoded mu-law byte</param>
        /// <param name="counter">The encoded mu-law byte</param>
        /// <returns>A array of strings with sip responses</returns>
        public static string[] getResponse(string request, string codec, string ip, int counter, bool changePort){

            string[] response ={"","","","",""};
            // [0] - Id
            // [1] - Port
            // [2] - Number of Messages returned
            // [3] - Msg 1
            // [4] - Msg 2

            StringBuilder Header = new StringBuilder();
            string[] lines = Regex.Split(request, "\r\n");

            String msgID ="";
            string portRTPin = "0";
            int portRTPout=0;
            

            switch (request.Substring(0, 3))
            {
                case "INV":

                    // Response > 180 RINGING
                    portRTPin = GetPortRDP(lines.FirstOrDefault(s => s.Contains("m=audio")));
                    if (changePort)
                    {
                        portRTPout = Convert.ToInt32(portRTPin) + 1;
                    }
                    else
                    {
                        portRTPout = Convert.ToInt32(portRTPin);
                    }
                    msgID = "T" + counter.ToString() + "-RTPto-" + portRTPin;
                    Header.Clear();
                    Header.Append("SIP/2.0 180 Ringing");
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("Via: ")));
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("From: ")));
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("To: ")) + ";tag=" + msgID);
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("Call-ID: ")));
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("CSeq: ")));
                    Header.Append("\r\n");
                    Header.Append("Contact: <sip:" + ip + ":" + portRTPin + ";transport=UDP>");
                    Header.Append("\r\n");
                    Header.Append("Content-Length: 0");
                    Header.Append("\r\n");
                    Header.Append("\r\n");

                    response[0] = msgID;
                    response[1] = portRTPout.ToString();
                    response[2] = "2";
                    response[3] = Header.ToString();

                    // Response > 200 OK
                    StringBuilder Message = new StringBuilder();
                    Message.Clear();
                    Message.Append("v=0");
                    Message.Append("\r\n");
                    Message.Append("o=ssRTP " + counter + " " + counter + " IN IP4 " + ip);
                    Message.Append("\r\n");
                    Message.Append("s=ssRTP");
                    Message.Append("\r\n");
                    Message.Append("c=IN IP4 " + ip);
                    Message.Append("\r\n");
                    Message.Append("t=0 0");
                    Message.Append("\r\n");
                    switch (codec)
                    {
                        case "0": //PCMU
                            {
                                Message.Append("m=audio " + portRTPout.ToString() + " RTP/AVP 0"); // replace do codec
                                Message.Append("\r\n");
                                Message.Append("a=rtpmap:0 PCMU/8000"); // replace do codec
                                break;
                            }
                        case "3": // GSM
                            {
                                Message.Append("m=audio " + portRTPout.ToString() + " RTP/AVP 3"); // replace do codec
                                Message.Append("\r\n");
                                Message.Append("a=rtpmap:3 GSM/8000"); // replace do codec
                                break;
                            }
                        case "8": //PCMA
                            {
                                Message.Append("m=audio " + portRTPout.ToString() + " RTP/AVP 8"); // replace do codec
                                Message.Append("\r\n");
                                Message.Append("a=rtpmap:8 PCMA/8000"); // replace do codec
                                break;
                            }
                        default:  // reply with the codec received
                            {
                                if (changePort)
                                {
                                    string a = lines.FirstOrDefault(s => s.Contains("m="));
                                    string final = a.Replace(portRTPin, portRTPout.ToString());
                                    Message.Append(final); // replace do codec
                                }
                                else
                                {
                                    Message.Append(lines.FirstOrDefault(s => s.Contains("m="))); // replace do codec
                                }
                                Message.Append("\r\n");
                                Message.Append(lines.FirstOrDefault(s => s.Contains("a="))); // replace do codec
                                break;
                            }
                    }
                    Message.Append("\r\n");
                    Message.Append("\r\n");

                    Header.Clear();
                    Header.Append("SIP/2.0 200 OK");
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("Via: ")));                                         // Via
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("From: ")));                                         // From
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("To: ")) + ";tag=" + msgID);                       // To
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("Call-ID: ")));                                         // Call ID
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("CSeq: ")));                                         // CSeq
                    Header.Append("\r\n");
                    Header.Append("Contact: <sip:" + ip + ":" + portRTPin + ";transport=UDP>");    // Contact
                    Header.Append("\r\n");
                    Header.Append("Content-Type: application/sdp");                             // Content-Type
                    Header.Append("\r\n");
                    Header.Append("Content-Length: " + Message.Length.ToString());              // Content-lenght
                    Header.Append("\r\n");
                    Header.Append("\r\n");

                    response[4] = Header.ToString() + Message.ToString();

                    break;
                case "ACK":
                    // No reply on ACK. Do nothing. RTP receive start earlier...
                    msgID = GetMsgID(lines.FirstOrDefault(s => s.Contains("To: ")));
                    response[0] = msgID;
                    response[2] = "0";
                    break;
                case "BYE":
                    // Response > 200 OK
                    msgID = GetMsgID(lines.FirstOrDefault(s => s.Contains("To: ")));
                    Header.Clear();
                    Header.Append("SIP/2.0 200 OK");
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("Via: ")));  
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("From: "))); 
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("To: "))); 
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("Call-ID: ")));  
                    Header.Append("\r\n");
                    Header.Append(lines.FirstOrDefault(s => s.Contains("CSeq: "))); 
                    Header.Append("\r\n");
                    Header.Append("Contact: <sip:" + ip + ":" + portRTPin + ";transport=UDP>");
                    Header.Append("\r\n");
                    Header.Append("Content-Length: 0");
                    Header.Append("\r\n");
                    Header.Append("\r\n");

                    response[0] = msgID;
                    response[1] = portRTPin;
                    response[2] = "1";
                    response[3] = Header.ToString();
                    break;
                default:
                    break;
            }
            return response;
        }

        /// <summary>
        /// Get RTP Port from the request sip header
        /// </summary>
        /// <param name="str">String to search the Rtp port</param>
        /// <returns>Rtp port value</returns>
        private static string GetPortRDP(string str)
        {
            string[] _msgID = Regex.Split(str, " ");
            return _msgID[1].ToString();
        }

       /// <summary>
       /// Get SIP message ID from the request sip header
       /// </summary>
       /// <param name="str">String to search the Sip message ID</param>
       /// <returns>SIP message ID value</returns>
        private static string GetMsgID(string str)
        {
            string[] _msgID = Regex.Split(str, "=");
            return _msgID[1].ToString();
        }
    }
}
